YS電子工作ラボ

SPI 制御による
   DAコンバータ出力

                                 (→プロジェクトファイル(Harmony Ver.2.04版 ) ダウンロード


  PIC32MZを使い、SPI モジュールを内臓したマイクロチップのD/AコンバータMCP4922をSPI制御してD/A変換を行った例を紹介します。

 <仕様>
  ・ DAコンバータに正弦波電圧を出力する。
  ・ PICはPIC32MZ2048EFH100を用い、DAコンバータはMCP4922を用いる。
  ・ 1度毎の正弦波テーブルを生成し、割り込みによりこのデータを500Hzで(2 msec毎に)サンプリングしてSPI通信でD/Aコンバータ
    MCP4922に伝送する。
     SPI諸元(PIC側): 
         モード: マスターモード
         SPIクロック周波数: 10MHz
         データ幅: 16ビット         
         データモード: IDLE Low   ACTIVE High
         遷移: クロックがACTIVE(High) → IDLE(Low)に変化した時、MCP4922レジスタデータ変化
         データ抽出タイミング: データの後縁 
  ・ MCP4922(電源電圧+3.3V)からは、1.39Hz(注)、Vp-p 2.7V、分解能12ビットの正弦波電圧を出力する。
    出力ポートはVoutAとする。
        (注)1.39Hz = 500KHz ÷ 360
  ・ Harmonyの スタティックSPIライブラリとスタティクタイマライブらを用いる。
 

 <回路図>( → PDFファイル



 <外観>
     PIC32MZ評価ボード(→購入方法)を使った実験品の外観です。
     汎用モジュール評価ボード(段積みボード)には本テーマと関係ない部品が多々実装されています。




 <動作結果>     

 DAコンバータ MCP4922の
端子VoutAの出力電圧
 
1V/div
200msec/div 


<解説> 記載してある内容は要点だけです。 詳細はプロジェクトファイルを精読願います。
         (以下は、Harmony v2.04 をもとに作成しています。最新のバージョンとは異なることがあるかもしれませんので注意してください。)

  ■ MHC設定
   ■ Options

項目 ①Config設定
Device & Project Configuration
  > PIC32MZ2048 Device Configuration
②SPI設定1
Harmony Framework Configuration > Drivers
 > SPI
MHC
備考 デフォルトからの変更要領:
 FPLLIDIV: DIV3
 FPLLICLK: PLL_POSC
 POSCMOD: EC

システムクロック周波数: 200MHz
外部OSC: 24MHz
タイマ用ペリフェラルクロック
     周波数(PBCLK3): 100MHz


#pragma config FNOSC = SPLL
#pragma config POSCMOD = EC
#pragma config FPLLIDIV = DIV_3
#pragma config FPLLICLK = PLL_POSC
#pragma config FPLLMULT = MUL_50
#pragma config FPLLODIV = DIV_2 
デフォルトからの変更要領:
 □Use SPI Driver? チェックを入れる
 Driver Implementation: STATIC
 □Use Interrupt Mode? チェックをはずす
 □Use Polled Mode? チェックを入れる
 □Use 8bit Mode? チェックをはずす
 □Use 16bit Mode? チェックを入れる
項目 ③SPI設定2
Harmony Framework Configuration > Drivers
 > SPI
④タイマ
Harmony Framework Configuration > Drivers
 > Timer
 
備考 デフォルトからの変更要領:
 SPI Mocule ID: SPI_ID_4
 □Use Polled Mode? チェックを入れる
 Data Width: 16bit
 Clock Mode: DRV_SPI_CLOCK_MODE_IDLE_LOW_EDGE_FALL
デフォルトからの変更要領:
 □Use Timer driver? チェックを入れる
 Driver Implementation: STATIC
 Prescale: TMR_PRESCALE_VALUE_8
 Timer Period: 25000


   ■ Pin Settings

項目 ⑤ポート設定
MHC  
備考  デフォルトからの変更要領:
 RF2/Function: GPIO_OUT
        (CS用出力ポート設定)
 RD0/Function: SCK4
        (SPI4のSCK設定)
 RD11/Function: SDO4
        (SPI4のSDO設定)






■ app.cに、青字部分を追加します。

  ① delay_us( )、delay_ms( ) という NOPを使った 1μsec 、1msec単位の遅延関数をつくります。
     void delay_us(volatile unsigned int usec) //1μsec遅延
     {
        volatile int count;

     ……
     ……

  ② 正弦波形出力のテーブル作成用の関数を作成します。
     void SinTable() //Sin のテーブル作成
     {
        short int i;
        float PAI = 3.1416;

      ……
      ……

  ③ APP_Initialize ( )の中で、 Sin波形のテーブルを作成後、インターバルタイマの割り込みを許可します。
     SinTable();
     DRV_TMR0_Start(); //必須



以下、app.c






 ■ system_interrupt.c に 青字部分を追加します。

   ①割り込みハンドラの中に割り込み時の処理を記述します。
     デフォルトでインターバルタイマが選択されているので下記の(タイマ再書き込みの)記述は必要ありません。
     PLIB_TMR_Period16BitSet(TMR_ID_1,25000); //5 nsec x2 x 25000 x 8 = 10000nsec = 1000μsec = 2msec

   ②DAコンバータ MCP4922のCSを LOW("0")にセットします。
     LATFbits.LATF2 = 0; //MCP4922 CS = 0


   ③SPIモジュールに所要の16ビット信号を書き込んで、書き込みが完了するまで待ちます。
     更にMCP4922での処理が完了するまで待ちます。 
     PLIB_SPI_BufferWrite16bit(SPI_ID_4,(short int)(sinValue[angleValue] | 0b0001000000000000)); //送信データ送信
                        // SPI4BUF = (short int)(sinValue[angleValue] | 0b0001000000000000); //送信データ送信
                        //MP4922 制御コマンド
                        //VoutAにゲイン2で出力
                        //MCP4922への書き込みコマンド
                        //bit15(書き込みレジスタ選択)   1:VoutB   0:VoutA
                        //bit14(予備)
                        //bit13(出力ゲイン選択)  1:1倍   0:2倍 
                        //bit12(出力オフ制御)  1:出力ON  0:出力OFF 
                        //bit11-bit0 データ  MSBから順次送信される
     while(PLIB_SPI_TransmitBufferIsFull(SPI_ID_4)); //SPI4SRレジスタへの書込み完了
     // while(SPI4STATbits.SPITBF); //: SPI Transmit Buffer Full Status bit //SPI4SRレジスタへの書込み完了
     delay_us(20); //MCP4922の処理待ち


   ④ 角度を1度インクリメントします。 1周期(360度)になったら0度に戻します。
      angleValue++;
      if(angleValue >= 360)angleValue = 0;



   ⑤ DAコンバータ MCP4922のCSを HIGH("1")にセットします。
      LATFbits.LATF2 = 1; //MCP4922 CS = 1;


以下、System_interrupt.c